package com.hbwxz.compareprice;

import com.hbwxz.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.Stream;

/**
 * @author shenzw
 * @date 2023/12/19
 */
@Slf4j
public class ComparePriceDemo {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        // 串行执行
//        serialDemo(); // 比较结束，总耗时（秒） = 6.195

//        futureAndThreadPool(); // 比较结束，总耗时（秒） = 2.175

        CompletableFutureDemo(); // 比较结束，总耗时（秒） = 1.184

        log.info("比较结束，总耗时（秒） = {}", (System.currentTimeMillis() - startTime) / 1000.0);
    }

    /**
     * CompletableFuture演示
     */
    private static void CompletableFutureDemo() {
        CompletableFuture<PriceResult> tBao = CompletableFuture
                .supplyAsync(() -> getPlatformStrategyContext().getPriceResult("苹果12", "", "tBaoPrice"))
                .thenCombine(CompletableFuture.supplyAsync(() -> getPlatformStrategyContext().getDiscountResult("苹果12", "", "tBaoDiscount")),
                        ComparePriceDemo::computeRealPrice);

        CompletableFuture<PriceResult> jd = CompletableFuture
                .supplyAsync(() -> getPlatformStrategyContext().getPriceResult("苹果12", "", "jdPrice"))
                .thenCombine(CompletableFuture.supplyAsync(() -> getPlatformStrategyContext().getDiscountResult("苹果12", "", "jdDiscount")),
                        ComparePriceDemo::computeRealPrice);

        CompletableFuture<PriceResult> pdd = CompletableFuture
                .supplyAsync(() -> getPlatformStrategyContext().getPriceResult("苹果12", "", "pddPrice"))
                .thenCombine(CompletableFuture.supplyAsync(() -> getPlatformStrategyContext().getDiscountResult("苹果12", "", "pddDiscount")),
                        ComparePriceDemo::computeRealPrice);

        PriceResult priceResult = Stream.of(tBao, jd, pdd)
                .map(CompletableFuture::join)
                .filter(Objects::nonNull)
                .sorted(Comparator.comparingInt(PriceResult::getRealPrice))
                .findFirst()
                .get();

        CommonUtils.printThreadLog("比价结果 = " + priceResult);
    }

    /**
     * 使用 Future ➕ 线程池实现
     */
    private static void futureAndThreadPool() {
        ExecutorService executor = Executors.newFixedThreadPool(8);
        // 获取三方平台的最终价格
        Future<PriceResult> tBao = executor.submit(() -> getPriceResult(getPlatformStrategyContext(), "tBaoPrice", "tBaoDiscount"));

        Future<PriceResult> jd = executor.submit(() -> getPriceResult(getPlatformStrategyContext(), "jdPrice", "jdDiscount"));

        Future<PriceResult> pdd = executor.submit(() -> getPriceResult(getPlatformStrategyContext(), "pddPrice", "pddDiscount"));

        PriceResult priceResult = Stream.of(tBao, jd, pdd)
                .map(future -> {
                    try {
                        return future.get();
                    } catch (InterruptedException | ExecutionException ex) {
                        log.error("Future get is error.", ex);
                        return null;
                    } finally {
                        executor.shutdown();
                    }
                })
                .filter(Objects::nonNull)
                .min(Comparator.comparingInt(PriceResult::getRealPrice))
                .get();

        CommonUtils.printThreadLog("比价结果 = " + priceResult);
    }

    /**
     * 获取 PlatformStrategyContext 上下文
     *
     * @return PlatformStrategyContext
     */
    public static PlatformStrategyContext getPlatformStrategyContext() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PlatformStrategyContext.class);
        return context.getBean(PlatformStrategyContext.class);
    }


    /**
     * 串行获取各个平台的价格，进行比价
     */
    private static void serialDemo() {
        PlatformStrategyContext platformStrategyContext = getPlatformStrategyContext();
        // 获取淘宝的价格和折扣
        PriceResult tBao = getPriceResult(platformStrategyContext, "tBaoPrice", "tBaoDiscount");

        // 获取京东的价格和折扣
        PriceResult jd = getPriceResult(platformStrategyContext, "jdPrice", "jdDiscount");

        // 获取拼多多的价格和折扣
        PriceResult pdd = getPriceResult(platformStrategyContext, "pddPrice", "pddDiscount");

        // 比价
        PriceResult priceResult = Stream.of(tBao, jd, pdd)
                .min(Comparator.comparingInt(PriceResult::getRealPrice)).get();

        CommonUtils.printThreadLog("比价结果 = " + priceResult);

    }

    private static PriceResult getPriceResult(PlatformStrategyContext platformStrategyContext, String Price, String discount) {
        PriceResult priceResult = platformStrategyContext.getPriceResult("苹果12", "", Price);
        int discountResult = platformStrategyContext.getDiscountResult("苹果12", "", discount);
        return computeRealPrice(priceResult, discountResult);
    }

    /**
     * 计算商品的最终价格 = 平台价格 - 优惠价
     *
     * @param priceResult 商品比价实体
     * @param discount    折扣
     * @return PriceResult
     */
    public static PriceResult computeRealPrice(PriceResult priceResult, int discount) {
        priceResult.setRealPrice(priceResult.getPrice() - discount);
        priceResult.setDiscount(discount);
        CommonUtils.printThreadLog(String.format("最终价格计算完成 = 【%d】，最优惠平台为 = 【%s】", priceResult.getRealPrice(), priceResult.getPlatform()));
        return priceResult;
    }


}
